package com.xiaojie.rabbitmq.confirm;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.xiaojie.rabbitmq.MyConnection;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

/**
 * @author xiaojie
 * @version 1.0
 * @description: confirm模式保证消息可靠性，有三种方式
 * 方式一：channel.waitForConfirms()普通发送方确认模式；
 * 方式二：channel.waitForConfirmsOrDie()批量确认模式；
 * 方式三：channel.addConfirmListener()异步监听发送方确认模式；
 * @date 2021/9/28
 */
public class Provider {
    private static final String QUEUE_NAME = "myqueue";
    static Connection connection = null;
    static Channel channel = null;
    static String msg = "confirm模式保证消息可靠性。。。。";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        try {
            //创建连接
            connection = MyConnection.getConnection();
            //创建通道
            channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            channel.confirmSelect();//开启确认模式，确认消息已经被mq持久化到硬盘上
            channel.basicQos(1);//每次发送一条消息，并且收到消费者的ack之后才会发送第二条
            //如果异常进行重试，超过重试次数放弃执行
//            int i=1/0;
            //发送消息
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes(StandardCharsets.UTF_8));
            if (channel.waitForConfirms()) {
                //确认消息已经持久化到硬盘
                System.out.println("消息发送成功。。。。。。");
            }
        } catch (Exception e) {
            for (int i = 0; i < 3; i++) {
                //发送消息
                System.out.println("重试次数" + (i + 1));
                channel.basicPublish("", QUEUE_NAME, null, msg.getBytes(StandardCharsets.UTF_8));
                if (i >= 3) {
                    //实际生产时候，可以放到表中记录失败的消息，然后采取补偿措施
                    break;
                }
            }
        } finally {
            //关闭通道，关闭连接
            if (channel != null) {
                channel.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}
